package com.macro.mall.demo.service.impl;

import com.alibaba.fastjson.JSON;
import com.macro.mall.common.domain.EsDocDto;
import com.macro.mall.demo.dto.MatchQueryInfo;
import com.macro.mall.demo.dto.RequesSelectEs;
import com.macro.mall.demo.service.EsDocService;
import com.macro.mall.demo.service.EsIndexService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author：贾维斯
 * @Description: 描述
 * @name：RequesSelectEs
 * @Date：2024/10/21
 */
@Service
@Slf4j
public class EsDocServiceImpl implements EsDocService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private EsIndexService esIndexService;

    /**
     * 批量添加
     *
     * @param esDocDto 文档信息
     * @return
     */
    @Override
    public void batchAdd(EsDocDto esDocDto) {
        // 检查索引是否存在
        if (!esIndexService.exists(esDocDto.getIndexName())) {
            throw new RuntimeException("索引不存在");
        }

        List<Map<String, Object>> dataS = esDocDto.getDataS();
        BulkRequest bulkRequest = new BulkRequest();

        // 准备添加请求
        for (Map<String, Object> data : dataS) {
            String id =  data.get(esDocDto.getDocId()).toString(); // 获取每个文档的ID
            bulkRequest.add(new IndexRequest(esDocDto.getIndexName())
                    .id(id)
                    .source(data));
        }
        //执行批量添加
        if (bulkRequest.numberOfActions() > 0) {
            try {
                BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
                // 检查是否有失败
                if (bulkResponse.hasFailures()) {
                    log.error("批量添加失败: {}", bulkResponse.buildFailureMessage());

                    // 获取所有批量操作的结果
                    BulkItemResponse[] items = bulkResponse.getItems();

                    // 收集失败的文档 ID
                    List<String> failedIds = new ArrayList<>();
                    for (BulkItemResponse item : items) {
                        if (!item.isFailed()) {
                            String failedId = item.getId(); // 获取失败项的 ID
                            failedIds.add(failedId);
                        }
                    }

                    // 如果有失败的文档 ID，执行删除操作
                    if (!failedIds.isEmpty()) {
                        log.info("开始删除失败的文档: {}", failedIds);
                        batchDelete(esDocDto.getIndexName(), failedIds);  // 批量删除失败的文档
                    }

                    throw new RuntimeException("批量添加失败,请重新试一下");
                } else {
                    log.info("批量添加成功");
                }
            } catch (Exception e) {
                log.error("ES批量添加异常", e);
            }
        } else {
            log.warn("批量添加数据为空");
        }
    }

    /**
     * 批量删除
     *
     * @param indexName 索引名称
     * @param ids       多个id
     */
    @Override
    public void batchDelete(String indexName, List<String> ids) {
        // 检查索引是否存在
        if (!esIndexService.exists(indexName)) {
            throw new RuntimeException("索引不存在: " + indexName);
        }

        // 创建一个 BulkRequest 用于批量删除
        BulkRequest bulkRequest = new BulkRequest();
        log.info("开始从索引 " + indexName + " 批量删除文档: " + ids);

        for (String id : ids) {
            DeleteRequest deleteRequest = new DeleteRequest(indexName, id);
            bulkRequest.add(deleteRequest); // 将删除请求添加到批量请求中
        }

        // 执行批量请求
        try {
            BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
            if (bulkResponse.hasFailures()) {
                log.error("批量删除失败: " + bulkResponse.buildFailureMessage());
                List<String> failedIds = new ArrayList<>();
                for (BulkItemResponse itemResponse : bulkResponse) {
                    if (itemResponse.isFailed()) {
                        failedIds.add(itemResponse.getId());
                    }
                }
                log.error("失败的 ID 列表: " + failedIds);
            } else {
                log.info("成功从索引 " + indexName + " 删除了 " + ids.size() + " 个文档");
            }
        } catch (IOException e) {
            log.error("删除文档时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    @Override
    public List<Object> selectEs(RequesSelectEs requesSelectEs) {
        //索引名称非空校验
        if (!esIndexService.exists(requesSelectEs.getIndexName())) {
            return null;
        }
        //创建也结合，泛型自拟
        ArrayList<Object> list = new ArrayList<>();

        //创建request对象
        SearchRequest searchRequest = new SearchRequest(requesSelectEs.getIndexName());
        //指定查询条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //分页
        Integer pageNum = requesSelectEs.getPageNum();//页数
        Integer pageSize = requesSelectEs.getPageSize();//每页的条数

        if (pageNum!=null && pageSize!=null && pageNum>0 && pageSize>0) {
            //开始是：页数-1*条数 结束是条数
            sourceBuilder.from((pageNum-1)*pageSize).size(pageSize);
        }

        //排序
        String orderField = requesSelectEs.getOrderField(); //排序对象
        String orderType = requesSelectEs.getOrderType(); //排序模式

        //如果排序对象和排序模式都不为空，那么就排序
        if (!StringUtils.isAllBlank(orderField,orderType)) {
            sourceBuilder.sort(orderField,SortOrder.fromString(orderType));
        }
        //将查询条件放入查询的请求对象
        searchRequest.source(sourceBuilder);

        try {
            //将查询请求对象放进高级的客户端请求中
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            for (SearchHit hit : searchResponse.getHits().getHits()) {
                String sourceAsString = hit.getSourceAsString();
                list.add(JSON.parseObject(sourceAsString,Object.class));
            }
            //返回集合
            return list;
        } catch (IOException e) {
            throw new RuntimeException(e);
          
        }

    }

    @Override
    public List<Object> selectMatch(RequesSelectEs requesSelectEs) {
        //判断索引是否存在
        if (!esIndexService.exists(requesSelectEs.getIndexName())) {
            log.info("索引不存在，请联系额为");
            return null;
        }
        //创键请求对象
        SearchRequest searchRequest = new SearchRequest(requesSelectEs.getIndexName());
        //创建条件收集器
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //多条件拼接器
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //条件
        MatchQueryInfo matchQueryInfo = requesSelectEs.getMatchQueryInfo();
        String keyWord = matchQueryInfo.getKeyWord();
        List<String> searchFields = matchQueryInfo.getSearchFields();
        //判空检验
        if (searchFields!=null) {
            for (String searchField : searchFields) {
                if (searchField!=null) {
                    //多条件查询
                 boolQueryBuilder.should(QueryBuilders.matchQuery(searchField,keyWord));
                }
            }
        }
        sourceBuilder.query(boolQueryBuilder);
        Integer pageNum = requesSelectEs.getPageNum();
        Integer pageSize = requesSelectEs.getPageSize();
        String orderField = requesSelectEs.getOrderField();
        String orderType = requesSelectEs.getOrderType();
        List<Object> selectList =  selectList1(searchRequest,sourceBuilder,pageNum,pageSize,orderField,orderType);
        return selectList;
    }

    private List<Object> selectList1(SearchRequest searchRequest, SearchSourceBuilder sourceBuilder, Integer pageNum, Integer pageSize, String orderField, String orderType) {
        if (pageNum!=null && pageSize!=null && pageNum>0 && pageSize>0) {
            //开始是：页数-1*条数 结束是条数
            sourceBuilder.from((pageNum-1)*pageSize).size(pageSize);
        }

        //如果排序对象和排序模式都不为空，那么就排序
        if (!StringUtils.isAllBlank(orderField,orderType)) {
            sourceBuilder.sort(orderField,SortOrder.fromString(orderType));
        }
        //将条件放进查询请求中
        searchRequest.source(sourceBuilder);
        try {
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            ArrayList<Object> list = new ArrayList<>();
            for (SearchHit hit : searchResponse.getHits().getHits()) {
                String sourceAsString = hit.getSourceAsString();
                Object o = JSON.parseObject(sourceAsString, Object.class);
                list.add(o);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return null;
    }


}
